package com.wave.wavesystem.core.service;

import com.mybatisflex.core.query.QueryCondition;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.service.IService;
import com.mybatisflex.core.util.SqlUtil;
import com.wave.wavesystem.business.pojo.entity.UserEntity;
import com.wave.wavesystem.common.util.AuthUtil;
import com.wave.wavesystem.common.util.Func;
import wave.common.pojo.entity.BaseEntity;

import java.util.Collection;
import java.util.Map;

/**
 * 业务 service 继承该 接口 只要插入的实体类继承了 BaseEntity 的都可以自动填充基础字段
 *
 * @param <T>
 */
public interface WaveService<T> extends IService<T> {

    @Override
    default boolean save(T entity) {
        UserEntity operateUser = getOperateUser();
        if (Func.isEmpty(operateUser)) {
            return SqlUtil.toBool(this.getMapper().insert(entity, true));
        }
        if (entity instanceof BaseEntity) {
            ((BaseEntity) entity).setUpdateUser(operateUser.getId());
            ((BaseEntity) entity).setCreateUser(operateUser.getId());
        }
        return SqlUtil.toBool(this.getMapper().insert(entity, true));
    }

    @Override
    default boolean saveBatch(Collection<T> entities) {
        UserEntity operateUser = getOperateUser();
        if (Func.isEmpty(operateUser)) {
            return this.saveBatch(entities, 1000);
        }
        checkEntityCollection(entities, operateUser);
        return this.saveBatch(entities, 1000);
    }


    @Override
    default boolean saveOrUpdate(T entity) {
        UserEntity operateUser = getOperateUser();
        if (Func.isEmpty(operateUser)) {
            return SqlUtil.toBool(this.getMapper().insertOrUpdate(entity, true));
        }
        if (Func.isNotEmpty(entity)) {
            if (entity instanceof BaseEntity) {
                if (Func.isEmpty(((BaseEntity) entity).getId())) {
                    ((BaseEntity) entity).setCreateUser(operateUser.getId());
                }
                ((BaseEntity) entity).setUpdateUser(operateUser.getId());
            }
        }
        return SqlUtil.toBool(this.getMapper().insertOrUpdate(entity, true));
    }

    @Override
    default boolean saveOrUpdateBatch(Collection<T> entities) {
        UserEntity operateUser = getOperateUser();
        if (Func.isEmpty(operateUser)) {
            this.saveOrUpdateBatch(entities, 1000);
        }
        checkEntityCollection(entities, operateUser);
        return this.saveOrUpdateBatch(entities, 1000);
    }

    @Override
    default boolean updateById(T entity) {
        UserEntity operateUser = getOperateUser();
        if (Func.isEmpty(operateUser)) {
            return this.updateById(entity, true);
        }
        if (entity instanceof BaseEntity) {
            ((BaseEntity) entity).setUpdateUser(operateUser.getId());
            ((BaseEntity) entity).setCreateUser(operateUser.getId());
        }
        return this.updateById(entity, true);
    }

    @Override
    default boolean updateById(T entity, boolean ignoreNulls) {
        UserEntity operateUser = getOperateUser();
        if (Func.isEmpty(operateUser)) {
            return SqlUtil.toBool(this.getMapper().update(entity, ignoreNulls));
        }
        if (entity instanceof BaseEntity) {
            ((BaseEntity) entity).setUpdateUser(operateUser.getId());
            ((BaseEntity) entity).setCreateUser(operateUser.getId());
        }
        return SqlUtil.toBool(this.getMapper().update(entity, ignoreNulls));
    }

    @Override
    default boolean update(T entity, Map<String, Object> query) {
        UserEntity operateUser = getOperateUser();
        if (Func.isEmpty(operateUser)) {
            return this.update(entity, this.query().where(query));
        }
        if (entity instanceof BaseEntity) {
            ((BaseEntity) entity).setUpdateUser(operateUser.getId());
            ((BaseEntity) entity).setCreateUser(operateUser.getId());
        }
        return this.update(entity, this.query().where(query));
    }

    @Override
    default boolean update(T entity, QueryWrapper query) {
        UserEntity operateUser = getOperateUser();
        if (Func.isEmpty(operateUser)) {
            return SqlUtil.toBool(this.getMapper().updateByQuery(entity, query));
        }
        if (entity instanceof BaseEntity) {
            ((BaseEntity) entity).setUpdateUser(operateUser.getId());
            ((BaseEntity) entity).setCreateUser(operateUser.getId());
        }
        return SqlUtil.toBool(this.getMapper().updateByQuery(entity, query));
    }

    @Override
    default boolean update(T entity, QueryCondition condition) {
        UserEntity operateUser = getOperateUser();
        if (Func.isEmpty(operateUser)) {
            return this.update(entity, this.query().where(condition));
        }
        if (entity instanceof BaseEntity) {
            ((BaseEntity) entity).setUpdateUser(operateUser.getId());
            ((BaseEntity) entity).setCreateUser(operateUser.getId());
        }
        return this.update(entity, this.query().where(condition));
    }

    @Override
    default boolean updateBatch(Collection<T> entities) {
        UserEntity operateUser = AuthUtil.getUser();
        if (Func.isEmpty(operateUser)) {
            return this.updateBatch(entities, 1000);
        }
        checkEntityCollection(entities, operateUser);
        return this.updateBatch(entities, 1000);
    }

    @Override
    default boolean updateBatch(Collection<T> entities, boolean ignoreNulls) {
        UserEntity operateUser = AuthUtil.getUser();
        if (Func.isEmpty(operateUser)) {
            return this.updateBatch(entities, 1000, ignoreNulls);
        }
        checkEntityCollection(entities, operateUser);
        return this.updateBatch(entities, 1000, ignoreNulls);
    }


    // 获取当前 操作用户
    private UserEntity getOperateUser() {
        return AuthUtil.getUser();
    }

    // 给批量修改 entity 设置基础信息
    private void checkEntityCollection(Collection<T> entities, UserEntity operateUser) {
        if (Func.isNotEmpty(entities)) {
            for (T entity : entities) {
                if (entity instanceof BaseEntity) {
                    if (Func.isEmpty(((BaseEntity) entity).getId())) {
                        ((BaseEntity) entity).setCreateUser(operateUser.getId());
                    }
                    ((BaseEntity) entity).setUpdateUser(operateUser.getId());
                }
            }
        }
    }

}
